package com.wchat.network.message.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import android.content.Context;
import android.content.Intent;

import com.wchat.network.Actions;
import com.wchat.network.Configs;
import com.wchat.network.message.Message;

public class FileMessageController {

	private static FileMessageController INSTANCE = null;

	private FileMessageController() {

	}

	public static FileMessageController getInstance() {
		if (INSTANCE == null)
			INSTANCE = new FileMessageController();
		return INSTANCE;
	}

	/** return socket port */
	public int prepareFileServer(Context context, FileMessage fileMessage) {
		ServerSocket serverSocket = Configs.getAvailableServerSocket();

		FileSenderThread thread = new FileSenderThread(context, fileMessage, serverSocket);
		thread.start();
		return serverSocket.getLocalPort();
	}

	public void receiveFile(Context context, FileReadyMessage message) {
		FileReceiverThread thread = new FileReceiverThread(context, message);
		thread.start();
	}

	private static class FileSenderThread extends Thread {

		Context context;
		ServerSocket serverSocket = null;
		FileMessage message;

		public FileSenderThread(Context context, FileMessage fileMessage, ServerSocket serverSocket) {
			super();
			this.context = context;
			this.message = fileMessage;
			this.serverSocket = serverSocket;
		}

		@Override
		public void run() {

			Socket socket = null;
			try {
				socket = serverSocket.accept();
				OutputStream out = null;
				InputStream in = null;
				try {
					out = socket.getOutputStream();
					File file = new File(message.getFileInfo().path);
					in = new FileInputStream(file);
					int read = 0;
					byte[] buffer = new byte[1 << 12];

					Intent intent = new Intent(Actions.ACTION_FILE_TRANSFER_START);
					intent.putExtra("message", message);
					context.sendBroadcast(intent);

					while ((read = in.read(buffer)) != -1) {
						out.write(buffer, 0, read);
					}
					out.flush();

					intent = new Intent(Actions.ACTION_FILE_TRANSFER_SUCCESS);
					intent.putExtra("message", message);
					context.sendBroadcast(intent);
				} finally {
					if (out != null)
						try {
							out.close();
						} catch (Exception e) {

						}
					if (in != null)
						try {
							in.close();
						} catch (Exception e) {

						}
				}

			} catch (IOException e) {
				Intent intent = new Intent(Actions.ACTION_FILE_TRANSFER_FAILED);
				intent.putExtra("message", message);
				context.sendBroadcast(intent);
				Configs.log("sending file error", e);
			} finally {
				if (socket != null)
					try {
						socket.close();
					} catch (Exception e) {

					}
				if (serverSocket != null)
					try {
						serverSocket.close();
					} catch (Exception e) {

					}
			}
		}
	}

	private static class FileReceiverThread extends Thread {

		Context context;
		FileReadyMessage fileReadyMessage;
		FileMessage fileMessage;

		public FileReceiverThread(Context context, FileReadyMessage message) {
			super();
			this.context = context;
			this.fileReadyMessage = message;
			fileMessage = fileReadyMessage.getOriginalMessage();
			fileMessage.setGroup(fileReadyMessage.getGroup());
		}

		@Override
		public void run() {
			Socket socket = null;
			try {
				socket = new Socket(fileReadyMessage.getFrom(), fileReadyMessage.getDataPort());
				OutputStream out = null;
				InputStream in = null;
				try {
					File file = new File(fileMessage.getType() == Message.TYPE_IMAGE ? Configs.getImageDir() : Configs.getFileDir(),
							fileMessage.getFileInfo().fileName);
					out = new FileOutputStream(file);
					in = socket.getInputStream();
					int read = 0;
					byte[] buffer = new byte[1 << 12];

					Intent intent = new Intent(Actions.ACTION_FILE_TRANSFER_START);
					intent.putExtra("message", fileMessage);
					intent.putExtra("file", file);
					context.sendBroadcast(intent);

					while ((read = in.read(buffer)) != -1) {
						out.write(buffer, 0, read);
					}
					out.flush();

					intent = new Intent(Actions.ACTION_FILE_TRANSFER_SUCCESS);
					intent.putExtra("message", fileMessage);
					intent.putExtra("file", file);
					context.sendBroadcast(intent);
				} finally {
					if (out != null)
						try {
							out.close();
						} catch (Exception e) {

						}
					if (in != null)
						try {
							in.close();
						} catch (Exception e) {

						}
				}

			} catch (IOException e) {
				Intent intent = new Intent(Actions.ACTION_FILE_TRANSFER_FAILED);
				intent.putExtra("message", fileMessage);
				context.sendBroadcast(intent);
				Configs.log("sending file error", e);
			} finally {
				if (socket != null)
					try {
						socket.close();
					} catch (Exception e) {

					}
			}
		}
	}
}
